import UIKit

/**
    B站：https://www.bilibili.com/video/BV144411C7Gg?p=47

    第47课 错误捕获和处理
 */

// 回顾下知识
//              String 为枚举值类型
//                      Error为协议
enum TestError: String, Error {
    case error1 = "错误1"
    case error2 = "错误2"
}

// 1. 这个 play 可能会抛出错误的写法，后面加个 throw
func play(param: Int) throws {
    if (param < 0) {
        throw TestError.error1
    } else if (param >= 0 && param <= 10) {
        throw TestError.error2
    }
    
    print("正常运行")
}

// 2. 带有返回值的 抛出异常 函数
func play2(param: Int) throws -> String {
    if (param < 0) {
        throw TestError.error1
    } else if (param >= 0 && param <= 10) {
        throw TestError.error2
    }
    
    print("正常运行")
    return "hello world"
}


// -------------------------------------------------------
// *** 进行捕获 *****
// --- 写法1： do.catch --

do {
//    try play(param: -1) // 可切换方便 被注释掉了
//    try play(param: 5) // 可切换方便 被注释掉了
    try play(param: 15)
} catch TestError.error1 {
    print("play1", TestError.error1.rawValue)
} catch TestError.error2 {
    print("play1", TestError.error2.rawValue)
}


do {
    let value = try play2(param: -1) // 可切换方便 被注释掉了
//    let value = try play2(param: 5) // 可切换方便 被注释掉了
//    let value = try play2(param: 15)
    print("value=", value)
} catch TestError.error1 {
    print("play2", TestError.error1.rawValue)
} catch TestError.error2 {
    print("play2", TestError.error2.rawValue)
}



// --- 写法2： try? / try!  --
// try 后面可能有值，可能没有值， try?
// try 后面一定是有值的， try!

let value = try? play2(param: 0)
print("value=", value ?? "unkonw")


let value2 = try? play2(param: 10)
print("value2=", value2 ?? "unkonw 2") // ?? 判断可选类型
print("value2=", value2 != nil ? value2! : "unkonw 2") // 三元运算符 判断可选类型
if let p = value { // if 判断可选类型
    print(p)
} else {
    print("value2 --- unknow")
}



let value3 = try! play2(param: 15)
print("value3=", value3)



defer {
    // 不论捕获 是 成功/失败 都会在这里执行
    // 多个 [do.catch] 或者 [try],这里仅需要一个
    
    // 在所有捕获结果，才会执行这里
    print("defer")
}

print("end")


// --------------------------

debugPrint("aa")


func sendEE(param: TestError) {
    print("send=", param.rawValue)
}

sendEE(param: .error1)
sendEE(param: .error2)
